#ifndef _RECT_CACHE_H_
#define _RECT_CACHE_H_

#include "woopsiarray.h"
#include "gadget.h"

namespace WoopsiUI {

	/**
	 * Maintains a list of foreground (ie. above children) and background (with
	 * child overlapped-rects removed) rectangles representing the visible
	 * portions of a gadget.
	 */
	class RectCache {
	public:

		/**
		 * Constructor.
		 * @param gadget Gadget that contains the rect cache.
		 */
		RectCache(const Gadget* gadget);

		/**
		 * Destructor.
		 */
		inline ~RectCache() {
			delete _foregroundRegions;
			delete _backgroundRegions;
		};

		/**
		 * Rebuild the cache if it is invalid.
		 */
		void cache();

		/**
		 * Invalidates the cache.
		 */
		inline void invalidate() {
			_foregroundInvalid = true;
			_backgroundInvalid = true;
		};

		/**
		 * Return the list of background regions.  These are regions that are
		 * not overlapped by child gadgets.
		 * @return The list of background regions.
		 */
		inline WoopsiArray<Rect>* getBackgroundRegions() { return _backgroundRegions; };

		/**
		 * Return the list of foreground regions.  These are regions that
		 * represent the entire visible surface of the gadget - that is, any
		 * regions not overlapped by ancestors or sublings of the gadget -
		 * including any regions that are actually overlapped by child gadgets.
		 * @return The list of foreground regions.
		 */
		inline WoopsiArray<Rect>* getForegroundRegions() { return _foregroundRegions; };

		/**
		 * Works out which rectangles in the invalidRectangles list overlap this
		 * gadget, then cuts the rectangles into smaller pieces.  The
		 * overlapping pieces are pushed into validRects, and the
		 * non-overlapping pieces are pushed back into the invalidRects vector.
		 * @param invalidRectangles A vector of regions that need to be tested
		 * for collisions against this gadget; they represent regions that need
		 * to be redrawn.
		 * @param validRects A vector of regions that represents areas of the
		 * display that do not need to be redrawn.
		 */
		void splitRectangles(WoopsiArray<Rect>* invalidRectangles, WoopsiArray<Rect>* validRects) const;

		/**
		 * Move any rectangles from the visibleRects list that overlap this
		 * gadget into the invisibleRects list.  Used during visible region
		 * calculations.
		 * @param visibleRects A vector of regions that are not overlapped.
		 * @param invisibleRects A vector of regions that are overlapped.
		 * @param gadget The gadget that requested the lists.
		 * @see splitRectangles()
		 */
		void removeOverlappedRects(WoopsiArray<Rect>* visibleRects, WoopsiArray<Rect>* invisibleRects, const Gadget* gadget) const;

		/**
		 * Marks all foreground rects dirty.  All rects are sent to the
		 * DisplayController for redraw.  Since all foreground rects are sent,
		 * not background rects, this means that all of the owning gadget's
		 * children will also be redrawn next time the display is refreshed.
		 */
		void markRectsDamaged() const;
		
		/**
		 * Marks a specific rect as dirty.  The rect's co-ordinates should be in
		 * Woopsi-space.  The rect is automatically clipped and split so that
		 * only regions of it that intersect the foreground rects are redrawn.
		 * @param rect Rect to mark as dirty.
		 */
		void markRectDamaged(const Rect& rect) const;

	private:
		WoopsiArray<Rect>* _foregroundRegions;				/**< List of the gadget's visible regions */
		WoopsiArray<Rect>* _backgroundRegions;				/**< List of the gadget's visible regions with child rects removed */
		const Gadget* _gadget;								/**< Owning gadget */
		bool _foregroundInvalid;							/**< True if the foreground cache needs refreshing */
		bool _backgroundInvalid;							/**< True if the background cache needs refreshing */

		/**
		 * Cache the foreground regions.
		 */
		void cacheForegroundRegions();

		/**
		 * Cache the background regions.
		 */
		void cacheBackgroundRegions();

	};
}

#endif
